/**
 * Copyright (c) 2019 Coder League
 * All rights reserved.
 *
 * File：MobileShoppingCartService.java
 * History:
 *         2019年6月27日: Initially created, wangjb.
 */
package club.coderleague.ilsp.service.mobile.shoppingcarts;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import club.coderleague.ilsp.common.config.properties.FileUploadSettings;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder;
import club.coderleague.ilsp.common.domain.beans.PreferentialResult;
import club.coderleague.ilsp.common.domain.beans.ReceivingAddressesExtension;
import club.coderleague.ilsp.common.domain.beans.ShoppingCartSettlementMerchantExtension;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder.OnlineGood;
import club.coderleague.ilsp.common.domain.beans.OnlineOrder.OrderMerchant;
import club.coderleague.ilsp.common.domain.enums.EntityState;
import club.coderleague.ilsp.common.domain.enums.OrderDeliveryMode;
import club.coderleague.ilsp.common.domain.enums.OrderDeliveryTime;
import club.coderleague.ilsp.common.domain.enums.OrderPaymentMode;
import club.coderleague.ilsp.dao.AreasDao;
import club.coderleague.ilsp.dao.ReceivingAddressesDao;
import club.coderleague.ilsp.dao.ShoppingCartsDao;
import club.coderleague.ilsp.entities.Areas;
import club.coderleague.ilsp.entities.Receivingaddresses;
import club.coderleague.ilsp.service.orders.OrdersService;

/**
 * WeChat - 购物车业务处理。
 * @author wangjb
 */
@Service
public class MobileShoppingCartService {
	
	/**
	 * - 购物车数据访问对象。
	 */
	@Autowired ShoppingCartsDao shoppingCartsDao;
	
	/**
	 * - 收货地址数据访问对象。
	 */
	@Autowired ReceivingAddressesDao addressesDao;
	
	/**
	 * -订单接口。
	 */
	@Autowired OrdersService orderService;
	
	/**
	 * - 区域数据访问接口。
	 */
	@Autowired AreasDao areaDao;
	
	/**
	 * -附件配置表。
	 */
	@Autowired FileUploadSettings upload;

	/**
	 * - 查询会员购物车数据。
	 * @author wangjb 2019年6月27日。
	 * @param memberid
	 * @return
	 */
	public Map<String, Object> getShoppingCartListByMemberIdService(Long memberid) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<ShoppingCartSettlementMerchantExtension> settlementMerchantList = this.shoppingCartsDao.getShoppingCartSettlementMerchantByMemberidDao(false, memberid, false);
		List<Map<String, Object>> goodSaleList = this.shoppingCartsDao.getShoppingCartListByMemberIdDao(false, memberid, false);
		for (ShoppingCartSettlementMerchantExtension scsm : settlementMerchantList) {
			boolean selectstate = true;
			for (Map<String, Object> map : goodSaleList) {
				if (scsm.getEntityid().equals(map.get("merchantid")) && !(Boolean)map.get("selectstate")) selectstate = false;
			}
			scsm.setSelectstate(selectstate);
		}
		
		Double totalPrice = 0.0;
		for (Map<String, Object> map : goodSaleList) {
			if ((Boolean)map.get("selectstate")) {
				totalPrice += (Double)map.get("goodprice") * (Double)map.get("goodnumber");
			}
			// 商品封面。
			if (map.get("photopath") != null && StringUtils.isNotBlank(map.get("photopath").toString())) {
				map.put("photopath", this.upload.getVirtual() + this.upload.getGoodPhotosPath() +map.get("photopath").toString());
			}
		}
		result.put("merchantObj", settlementMerchantList);
		result.put("goodSaleList", goodSaleList);
		result.put("totalPrice", totalPrice == 0.0 ? 0.00 : new DecimalFormat("#.00").format(totalPrice));
		return result;
	}

	/**
	 * -查询确认订单页面数据。
	 * @author wangjb 2019年6月29日。
	 * @param buynow 是否立即购买。
	 * @param memberid 会员id。
	 * @return
	 */
	public Map<String, Object> getShoppingCartSettlementDataByParamService(Boolean buynow, Long memberid) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<ShoppingCartSettlementMerchantExtension> settlementMerchantList = this.shoppingCartsDao.getShoppingCartSettlementMerchantByMemberidDao(buynow, memberid, true);
		List<Map<String, Object>> goodSaleList = this.shoppingCartsDao.getShoppingCartListByMemberIdDao(buynow, memberid, true);
		Double totalPrice = 0.0; // 购买商品总价。
		Double totalGood = 0.0; // 购买商品总数。
		for (Map<String, Object> map : goodSaleList) {
			double goodTotalPrice = (Double)map.get("goodnumber") * (Double)map.get("goodprice");
			totalGood += (Double)map.get("goodnumber");
			totalPrice += goodTotalPrice;
			if (map.get("goodstock") != null && StringUtils.isNotBlank(map.get("goodstock").toString())) { // 商品库存。
				map.put("goodstock", Math.round((double)map.get("goodstock")) - (double)map.get("goodstock") == 0 ? (int)(double)map.get("goodstock") : map.get("goodstock")); // 库存。
			} else map.put("goodstock", 0);
			if (map.get("goodnumber") != null && StringUtils.isNotBlank(map.get("goodnumber").toString())) { // 商品价格。
				map.put("goodnumber", Math.round((double)map.get("goodnumber")) - (double)map.get("goodnumber") == 0 ? (int)(double)map.get("goodnumber") : map.get("goodnumber")); // 购买数量。
			} else map.put("goodnumber", 0);
			map.put("goodTotalPrice", goodTotalPrice); // 购买总金额。
			// 商品封面。
			if (map.get("photopath") != null && StringUtils.isNotBlank(map.get("photopath").toString())) {
				map.put("photopath", this.upload.getVirtual() + this.upload.getGoodPhotosPath() +map.get("photopath").toString());
			}
		}
		// 核算钻石优惠。
		PreferentialResult<Integer> preferential = this.orderService.calculateDiamondPreferential(memberid, 0, totalPrice, buynow);
		// 计算配送时间。
		List<Map<String, Object>> dayNumList = new ArrayList<Map<String,Object>>();
		List<Map<String, Object>> timeIntervalList = new ArrayList<Map<String,Object>>();
		Map<String, Object> dayMap = new LinkedHashMap<String, Object>(); // 天数。
		dayMap.put("dayType", "标准时间");
		dayMap.put("did", "standard");
		dayNumList.add(0, dayMap);
		Map<String, Object> timeMap = new LinkedHashMap<String, Object>(); // 时间区间。
		timeMap.put("timeInterval", "标准到达");
		timeMap.put("pid", "standard");
		timeIntervalList.add(timeMap);
		Date date = new Date();
		int k = 0;
		for (int i = 1; i <= 7; i++) {
			if (i == 1) {
				SimpleDateFormat format = new SimpleDateFormat("HH");
				int hour = Integer.parseInt(format.format(date)) + 2; // 当前时间加2小时。 
				k ++;
				if (hour <= 19) { // 当前时间加2小时小于晚上7点可配送。
					String pid = String.valueOf(date.getTime());
					dayMap = new LinkedHashMap<String, Object>();
					dayMap.put("dayType", getTimeDayNumAndWeekService(date));
					dayMap.put("did", pid);
					dayNumList.add(dayMap);
					if (hour < 7) hour = 9; // 从早上9点开始计算。
					for (int j = hour; j <= 19; j++) {
						if (hour >= 19) break;
						timeMap = new LinkedHashMap<String, Object>();
						timeMap.put("timeInterval", hour + ":00-" + (hour + 2) + ":00");
						timeMap.put("pid", pid);
						timeIntervalList.add(timeMap);
						hour += 2;
					}
					continue;
				} 
			}
			
			Date newDate = executrcalculateTimeService(k, date);
			String pid = String.valueOf(newDate.getTime());
			dayMap = new LinkedHashMap<String, Object>();
			dayMap.put("dayType", getTimeDayNumAndWeekService(newDate));
			dayMap.put("did", pid);
			dayNumList.add(dayMap);
			int hour = 9; // 早上7点开始进行配送。
			for (int j = 9; j < 19; j ++) {
				if (hour >= 19) break;
				timeMap = new LinkedHashMap<String, Object>();
				timeMap.put("timeInterval", hour + ":00-" + (hour + 2) + ":00");
				timeMap.put("pid", pid);
				timeIntervalList.add(timeMap);
				hour += 2;
			}
			k ++;
		}
		result.put("merchantObj", settlementMerchantList);
		result.put("goodSaleList", goodSaleList);
		result.put("totalPrice", new DecimalFormat("#.00").format(totalPrice));
		result.put("totalGood", totalGood);
		result.put("diamondAvailable", preferential.getAvailable()); // 可用优惠。
		result.put("diamondTotal", preferential.getTotal()); // 总体优惠。
//		result.put("diamondAvailable", 0); // 可用优惠。
//		result.put("diamondTotal", 0); // 总体优惠。
		result.put("dayNumList", dayNumList);
		result.put("timeIntervalList", timeIntervalList);
		return result;
	}
	
	static Date executrcalculateTimeService(int dayNum, Date date) {
		 Calendar ca = Calendar.getInstance();
		 ca.add(Calendar.DATE, dayNum);// 
		return ca.getTime();
	}
	
	/**
	 * -配送时间组转月/日/星期。
	 * @author wangjb 2019年7月19日。
	 * @param date 计算后的时间。
	 * @return
	 */
	static String getTimeDayNumAndWeekService(Date date) {
		String dayNumAndWeek = new SimpleDateFormat("MM月dd日").format(date);
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int wek = c.get(Calendar.DAY_OF_WEEK) - 1;
		switch (wek) {
			case 0:
				dayNumAndWeek += "[周日]";
				break;
			case 1:
				dayNumAndWeek += "[周一]";
				break;
			case 2:
				dayNumAndWeek += "[周二]";
				break;
			case 3:
				dayNumAndWeek += "[周三]";
				break;
			case 4:
				dayNumAndWeek += "[周四]";
				break;
			case 5:
				dayNumAndWeek += "[周五]";
				break;
			case 6:
				dayNumAndWeek += "[周六]";
				break;
		}
		return dayNumAndWeek;
	}
	
	/**
	 * WeChat 提交订单。
	 * @author wangjb 2019年7月7日。
	 * @param addressid 收货地址id。
	 * @param mid 商户id和备注。
	 * @param memberid 会员标识。
	 * @param dm 配送方式。
	 * @param pm 支付方式。
	 * @param dt 配送时间。
	 * @param result 返回做支付标识，
	 * @param buynow 立即购买。
	 * @param diamond 钻石数量。
	 * @param integral 积分数量。
	 * @throws Exception 
	 */
	public void executeSubmitOrderService(String addressid, String mid, Long memberid, Integer dm, Integer pm, String dt, Map<String, Object> result, 
			Boolean buynow, Integer diamond, Integer integral) throws Exception {
		OnlineOrder order = new OnlineOrder();
		OrderMerchant merchant = order.new OrderMerchant();
		List<OrderMerchant> orderMerchant = new ArrayList<OnlineOrder.OrderMerchant>();
		String[] midList = mid.split(",");
		for (String id : midList) {
			merchant = order.new OrderMerchant();
			String[] arr = id.split("_");
			Long merchantid = Long.valueOf(arr[0]);
			merchant.setMerchantid(merchantid);
			merchant.setDeliverycost(0.0);
			if (!"@".equals(arr[1])) merchant.setOrderremark(arr[1]);
			else merchant.setOrderremark(null);
			// 商品信息。
			String goodSales = arr[2];
			List<OnlineGood> onlineGoodList = new ArrayList<OnlineOrder.OnlineGood>();
			OnlineGood onlineGood = null;
			for (String goodData : goodSales.split("&")) {
				String[] saleArr = goodData.split("#");
				onlineGood = order.new OnlineGood();
				onlineGood.setSaleid(Long.valueOf(saleArr[0]));
				onlineGood.setGoodprice(Double.valueOf(saleArr[1]));
				onlineGood.setGoodnumber(Double.valueOf(saleArr[2]));
				onlineGoodList.add(onlineGood);
			}
			// 购买商品信息。
			merchant.setOnlinegoods(onlineGoodList);
			orderMerchant.add(merchant);
		}
		// 会员标识。
		order.setMemberid(memberid);
		
		// 商户信息。
		order.setOrdermerchants(orderMerchant); 
		// 立即购买。
		order.setBuynow(buynow); 
		// 收货地址id。
		order.setReceivingaddressesid(Long.valueOf(addressid)); 
		// 配送方式。
		if (dm.equals(OrderDeliveryMode.NO_DELIVERY.getValue())) order.setDeliverymode(OrderDeliveryMode.NO_DELIVERY);
		else if (dm.equals(OrderDeliveryMode.MARKET_DELIVERY.getValue())) order.setDeliverymode(OrderDeliveryMode.MARKET_DELIVERY);
		// 支付方式。
		OrderPaymentMode paymentmode = null;
		if (pm.equals(OrderPaymentMode.ALIPAY.getValue())) paymentmode = OrderPaymentMode.ALIPAY;
		else if (pm.equals(OrderPaymentMode.WECHAT.getValue())) paymentmode = OrderPaymentMode.WECHAT;
		else if (pm.equals(OrderPaymentMode.UNIONPAY.getValue())) paymentmode = OrderPaymentMode.UNIONPAY;
		order.setPaymentmode(paymentmode);
		// 配送时间处理。
		String[] deliveryTime = dt.split("_");
		OrderDeliveryTime orderDeliveryTime = null;
		Date deliverystarttime = null;
		Date deliveryendtime = null;
		if ("standard".equals(deliveryTime[0])) orderDeliveryTime = OrderDeliveryTime.STANDARD;
		else {
			orderDeliveryTime = OrderDeliveryTime.CUSTOMIZED; // 特定时间。
			String ms = deliveryTime[0];
			String hour = deliveryTime[1];
			Date date = new Date();
	        date.setTime(Long.parseLong(ms));
	        String day = new SimpleDateFormat("yyyy-MM-dd").format(date);
	        deliverystarttime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(day + " " + hour.split("-")[0]);
	        deliveryendtime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(day + " " + hour.split("-")[1]);
		}
		// 配送时间。
		order.setDeliverytime(orderDeliveryTime);
		// 配送起止时间。
		order.setDeliverystarttime(deliverystarttime);
		// 配送结束时间。
		order.setDeliveryendtime(deliveryendtime);
		// 钻石支付。
		order.setDiamondpay(diamond);
		// 积分支付。
		order.setIntegralpay(integral);
		// 生成订单;
		Long orderid = this.orderService.insertOnlineOrder(order);
		// 删除立即购买的数据。
		if (!buynow) this.shoppingCartsDao.deleteShoppingCartsBuyNowData(memberid);
		result.put("paymentkey", paymentmode.getKey()); // 支付关键值。
		result.put("orderid", orderid); // 订单id。
	}

	/**
	 * WeChat 查询会员标识下所有的收货地址。
	 * @author wangjb 2019年7月7日。
	 * @param memberid 会员id。
	 * @return
	 */
	public Map<String, Object> getReceivingAddressesByMemberIdService(Long memberid) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<ReceivingAddressesExtension> addressesList = this.addressesDao.findByMemberidAndEntitystate(memberid, EntityState.VALID.getValue(), false);
		for (ReceivingAddressesExtension addresses : addressesList) {
			String phone = addresses.getMobilephone().substring(0, 3) + "****" + addresses.getMobilephone().substring(7, addresses.getMobilephone().length());
			addresses.setMobilephone(phone);
		}
		ReceivingAddressesExtension address = this.addressesDao.findByMemberidAndDefaultaddressAndEntitystate(memberid, true, EntityState.VALID.getValue()); // 查询默认地址。
		if (address != null) address.setMobilephone(address.getMobilephone().substring(0, 3) + "****" + address.getMobilephone().substring(7, address.getMobilephone().length()));
		result.put("addressesList", addressesList);
		result.put("addresses", address);
		return result;
	}

	/**
	 * WeChat 根据收获地址id查询对象。
	 * @author wangjb 2019年7月7日。
	 * @param entityid 收货地址id。
	 * @param memberid 会员标识id。
	 * @return
	 */
	public ReceivingAddressesExtension getReceiverAddressByIdService(Long entityid, Long memberid) {
		boolean defaultaddress = false;
		if (entityid == null) { // 无收货地址id。查询会员默认地址。
			defaultaddress = true;
			entityid = memberid;
//			ReceivingAddressesExtension address = this.addressesDao.findByMemberidAndDefaultaddressAndEntitystate(memberid, true, EntityState.VALID.getValue());
//			return address;
		}
		ReceivingAddressesExtension address = this.addressesDao.findByMemberidAndDefaultaddressAndEntitystate(entityid, defaultaddress, EntityState.VALID.getValue());
		return address;
	}

	/**
	 * 新增或者编辑收货人地址。
	 * @author wangjb 2019年7月13日。
	 * @param result 返回结果说明。
	 * @param addresse 地址对象。
	 * @param memberid 会员标识。
	 */
	public void insertOrUpdateAddressesObjService(Map<String, Object> result, Receivingaddresses addresse, Long memberid) {
		if (addresse.getDefaultaddress()) { // 将被设置为默认地址。
			Receivingaddresses da = this.addressesDao.getReceivingAddressesByEntityidAndDefaultaddressDao(addresse.getEntityid(), addresse.getDefaultaddress(), memberid);
			if (da != null) da.setDefaultaddress(false);
		}
		addresse.setMemberid(memberid);
		this.addressesDao.save(addresse);
		result.put("entityid", addresse.getEntityid());
	}

	/**
	 * 新增个人地址查询区域。
	 * @author wangjb 2019年7月15日。
	 * @return
	 */
	public List<Map<String, Object>> getWetChatReceiviAreasService() {
		List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();
		List<Areas> provincialList = this.areaDao.getWetChatReceiviAreasDao(null); // 省级。
		for (Areas provincial : provincialList) { 
			Map<String, Object> provincialMap = new LinkedHashMap<String, Object>(); 
			provincialMap.put("CountryId", String.valueOf(provincial.getEntityid()));
			provincialMap.put("CountryName", provincial.getAreaname());
			List<Areas> cityList = this.areaDao.getWetChatReceiviAreasDao(provincial.getEntityid()); // 市级。
			List<Map<String, Object>> cityMapList = new ArrayList<Map<String,Object>>();
			for (Areas city : cityList) {
				Map<String, Object> cityMap = new LinkedHashMap<String, Object>();
				cityMap.put("ProvinceId", String.valueOf(city.getEntityid()));
				cityMap.put("ProvinceName", city.getAreaname());
				List<Areas> countyList = this.areaDao.getWetChatReceiviAreasDao(city.getEntityid()); // 区县。
				List<Map<String, Object>> countyMapList = new ArrayList<Map<String,Object>>();
				for (Areas county : countyList) {
					Map<String, Object> countyMap = new LinkedHashMap<String, Object>();
					countyMap.put("CityId", String.valueOf(county.getEntityid()));
					countyMap.put("CityName", county.getAreaname());
					List<Areas> streetList = this.areaDao.getWetChatReceiviAreasDao(county.getEntityid()); // 街道。
					List<Map<String, Object>> streetMapList = new ArrayList<Map<String,Object>>();
					for (Areas street : streetList) {
						Map<String, Object> streetMap = new LinkedHashMap<String, Object>();
						streetMap.put("CountyId", String.valueOf(street.getEntityid()));
						streetMap.put("CountyName", street.getAreaname());
						streetMapList.add(streetMap);
					}
					countyMapList.add(countyMap);
					countyMap.put("CountyList", streetMapList);
				}
				cityMapList.add(cityMap);
				cityMap.put("City", countyMapList);
			}
			provincialMap.put("Province", cityMapList);
			result.add(provincialMap);
		}
		return result;
	}

	
	/**
	 * 修改购物车商品选中状态。
	 * @author wangjb 2019年7月18日。
	 * @param result 返回操作提示。
	 * @param shoppingcartid 购物车id。
	 * @param userid 用户id。
	 * @param selectstate 商品选中状态。
	 */
	public void executeAmendSelectStateService(Map<String, Object> result, String shoppingcartid, Long userid, Boolean selectstate) {
		List<String> shoppingcartidList = new ArrayList<String>();
		for (String id : shoppingcartid.split(",")) {
			shoppingcartidList.add(id);
		}
		
		this.shoppingCartsDao.executeAmendSelectStateDao(shoppingcartidList, userid, selectstate);
	}

	/**
	 * 修改购物车商品数量。
	 * @author wangjb 2019年7月18日。
	 * @param result 返回操作提示。
	 * @param shoppingcartid 购物车id。
	 * @param goodnumber 商品数量。
	 * @param userid 用户id。
	 */
	public void executeAmendGoodNumberService(Map<String, Object> result, String shoppingcartid, Double goodnumber, Long userid, Boolean total) {
		this.shoppingCartsDao.executeAmendGoodNumberDao(shoppingcartid, goodnumber, userid);
	}

	/**
	 * 删除购物车里的商品。
	 * @author wangjb 2019年7月20日。
	 * @param result 返回操作结果说明。
	 * @param shoppingcartid 购物车id。
	 * @param userid 操作人员。
	 */
	public void executeDelShoppingCartGoodService(Map<String, Object> result, String shoppingcartid) {
		this.shoppingCartsDao.executeDelShoppingCartGoodDao(shoppingcartid);
	}

	/**
	 * -删除个人收货地址。
	 * @author wangjb 2019年9月16日。
	 * @param result 返回操作结果说明。
	 * @param entityid 收货地址id。
	 */
	public void deleteAddressesObjByEntityIdService(Map<String, Object> result, String entityid) {
		Receivingaddresses resses = this.addressesDao.getOne(Long.valueOf(entityid));
		resses.setEntitystate(EntityState.DELETED.getValue());
	}

}
